package com.aizuda.boot.modules.business.comment.service.impl;

import com.aizuda.boot.modules.business.comment.entity.CommentAttachmentEntity;
import com.aizuda.boot.modules.business.comment.entity.CommentEntity;
import com.aizuda.boot.modules.business.comment.entity.dto.CommentSaveReq;
import com.aizuda.boot.modules.business.comment.entity.vo.CommentRespDTO;
import com.aizuda.boot.modules.common.constant.enums.CommentTypeEnum;
import com.aizuda.boot.modules.business.comment.mapper.CommentAttachmentMapper;
import com.aizuda.boot.modules.business.comment.mapper.CommentMapper;
import com.aizuda.boot.modules.business.comment.service.CommentService;
import com.aizuda.boot.modules.business.contract.dto.UserInfo;
import com.aizuda.boot.modules.business.contract.util.AuthUtil;
import com.aizuda.boot.modules.business.permission.domain.response.EmployeeShowVO;
import com.aizuda.boot.modules.file.domain.entity.FileInfo;
import com.aizuda.boot.modules.file.mapper.FileInfoMapper;
import com.aizuda.boot.modules.system.entity.SysUser;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, CommentEntity> implements CommentService {

    @Resource
    private CommentAttachmentMapper attachmentMapper;
    @Resource
    private CommentMapper commentMapper;
    @Resource
    private FileInfoMapper fileInfoMapper;
    @Resource
    private ISysUserService sysUserService;

    public CommentServiceImpl(CommentAttachmentMapper attachmentMapper) {
        this.attachmentMapper = attachmentMapper;
    }

    @Override
    @Transactional
    public void saveCommentWithAttachments(CommentSaveReq req) {
        // 验证评论类型
        if (req.getCommentType() == null || !CommentTypeEnum.isValid(req.getCommentType())) {
            throw new IllegalArgumentException("评论类型无效，必须是0（协商评论）或1（审批评论）");
        }

        // 获取当前用户信息
        UserInfo currentUser = AuthUtil.getCurrentUser();
        if (currentUser == null || currentUser.getId() == null) {
            throw new IllegalArgumentException("无法获取当前用户信息，请重新登录");
        }

        // 保存评论
        CommentEntity comment = new CommentEntity();
        comment.setContractId(req.getContractId());
        comment.setUserId(currentUser.getId()); // 从当前用户上下文获取用户ID
        comment.setCommentText(req.getCommentText());
        comment.setCommentType(req.getCommentType());
        comment.setParentCommentId(req.getParentCommentId() != null ? req.getParentCommentId() : 0); // 支持回复评论
        
        // 手动设置时间字段，确保不为null
        LocalDateTime now = LocalDateTime.now();
        comment.setCreatedAt(now);
        comment.setUpdatedAt(now);
        
        baseMapper.insert(comment);

        // 保存附件
        if (req.getAttachments() != null && !req.getAttachments().isEmpty()) {
            List<CommentAttachmentEntity> attachments = req.getAttachments().stream().map(fileId -> {
                CommentAttachmentEntity attachment = new CommentAttachmentEntity();
                attachment.setCommentId(comment.getId());
                attachment.setFileId(fileId);
                // 设置时间字段，确保不为null
                attachment.setCreatedAt(now);
                attachment.setUpdatedAt(now);
                return attachment;
            }).collect(Collectors.toList());

            for (CommentAttachmentEntity attachment : attachments) {
                attachmentMapper.insert(attachment);
            }
        }
    }

    @Override
    public List<CommentRespDTO> getCommentTreeByContractId(Integer contractId) {
        // 1. 查询所有相关评论
        List<CommentEntity> comments = commentMapper.selectByContractId(contractId);
        if (comments == null || comments.isEmpty()) {
            return new ArrayList<>();
        }

        return buildCommentResponse(comments);
    }

    @Override
    public List<CommentRespDTO> getCommentTreeByContractIdAndType(Integer contractId, Integer commentType) {
        // 验证评论类型
        if (commentType != null && !CommentTypeEnum.isValid(commentType)) {
            throw new IllegalArgumentException("评论类型无效，必须是0（协商评论）或1（审批评论）");
        }

        // 1. 根据合同ID和评论类型查询评论
        List<CommentEntity> comments = commentMapper.selectByContractIdAndType(contractId, commentType);
        if (comments == null || comments.isEmpty()) {
            return new ArrayList<>();
        }

        return buildCommentResponse(comments);
    }

    /**
     * 构建评论响应数据
     */
    private List<CommentRespDTO> buildCommentResponse(List<CommentEntity> comments) {
        // 2. 批量查询所有附件
        List<Integer> commentIds = comments.stream().map(CommentEntity::getId).collect(Collectors.toList());
        Map<Integer, List<CommentAttachmentEntity>> attachmentsMap = getAttachmentsMap(commentIds);
        
        // 3. 获取所有文件信息
        Map<Long, FileInfo> fileInfoMap = getFileInfoMap(attachmentsMap);
        
        // 4. 获取所有用户信息
        Map<Long, EmployeeShowVO> userInfoMap = getUserInfoMap(comments);

        // 5. 构建评论树
        return buildCommentTree(comments, attachmentsMap, fileInfoMap, userInfoMap);
    }

    // 获取附件映射（commentId -> attachments）
    private Map<Integer, List<CommentAttachmentEntity>> getAttachmentsMap(List<Integer> commentIds) {
        LambdaQueryWrapper<CommentAttachmentEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(CommentAttachmentEntity::getCommentId, commentIds);
        List<CommentAttachmentEntity> attachments = attachmentMapper.selectList(queryWrapper);

        return attachments.stream()
                .collect(Collectors.groupingBy(CommentAttachmentEntity::getCommentId));
    }
    
    // 获取文件信息映射（fileId -> FileInfo）
    private Map<Long, FileInfo> getFileInfoMap(Map<Integer, List<CommentAttachmentEntity>> attachmentsMap) {
        // 收集所有的fileId
        List<Long> fileIds = attachmentsMap.values().stream()
                .flatMap(List::stream)
                .map(CommentAttachmentEntity::getFileId)
                .distinct()
                .collect(Collectors.toList());
        
        if (fileIds.isEmpty()) {
            return Map.of();
        }
        
        // 批量查询文件信息
        List<FileInfo> fileInfos = fileInfoMapper.selectBatchIds(fileIds);
        return fileInfos.stream()
                .collect(Collectors.toMap(FileInfo::getFileId, Function.identity()));
    }
    
    // 获取用户信息映射（userId -> EmployeeShowVO）
    private Map<Long, EmployeeShowVO> getUserInfoMap(List<CommentEntity> comments) {
        // 收集所有的userId
        List<Long> userIds = comments.stream()
                .map(CommentEntity::getUserId)
                .distinct()
                .collect(Collectors.toList());
        
        if (userIds.isEmpty()) {
            return Map.of();
        }
        
        // 批量查询用户信息
        List<SysUser> users = sysUserService.listByIds(userIds);
        return users.stream().map(user -> {
            EmployeeShowVO employeeShowVO = new EmployeeShowVO();
            employeeShowVO.setId(user.getId());
            employeeShowVO.setName(user.getNickName());
            employeeShowVO.setAvatar(user.getAvatar());
            return employeeShowVO;
        }).collect(Collectors.toMap(EmployeeShowVO::getId, Function.identity()));
    }

    // 构建树形结构
    private List<CommentRespDTO> buildCommentTree(List<CommentEntity> comments,
                                                   Map<Integer, List<CommentAttachmentEntity>> attachmentsMap,
                                                   Map<Long, FileInfo> fileInfoMap,
                                                   Map<Long, EmployeeShowVO> userInfoMap) {
        // 构建ID到DTO的映射
        Map<Integer, CommentRespDTO> commentMap = comments.stream()
                .map(comment -> {
                    CommentRespDTO resp = new CommentRespDTO();
                    BeanUtils.copyProperties(comment, resp);
                    resp.setAttachments(convertAttachments(attachmentsMap.get(comment.getId()), fileInfoMap));
                    resp.setUserInfo(userInfoMap.get(comment.getUserId()));
                    return resp;
                })
                .collect(Collectors.toMap(CommentRespDTO::getId, Function.identity()));

        // 构建树结构
        List<CommentRespDTO> result = new ArrayList<>();
        for (CommentRespDTO resp : commentMap.values()) {
            if (resp.getParentCommentId() == null || resp.getParentCommentId() == 0) {
                result.add(resp); // 顶级评论（兼容parentCommentId为null或0的情况）
            } else {
                CommentRespDTO parent = commentMap.get(resp.getParentCommentId());
                if (parent != null) {
                    parent.getChildComments().add(resp); // 添加子评论
                }
            }
        }
        return result;
    }

    // 转换附件实体到DTO
    private List<CommentRespDTO.CommentAttachmentResp> convertAttachments(List<CommentAttachmentEntity> attachments,
                                                                          Map<Long, FileInfo> fileInfoMap) {
        if (attachments == null || attachments.isEmpty()) {
            return new ArrayList<>();
        }
        return attachments.stream().map(att -> {
            CommentRespDTO.CommentAttachmentResp resp = new CommentRespDTO.CommentAttachmentResp();
            resp.setId(att.getId());
            resp.setFileId(att.getFileId());
            resp.setFileInfo(fileInfoMap.get(att.getFileId()));
            return resp;
        }).collect(Collectors.toList());
    }
}